package org.dfl.plugin.editor;

import org.dfl.messages.Messages;
import org.dfl.plugin.utils.WorkbenchUtil;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;

/**
 * DFL multipage editor - editor with tabs: diagram editor + description editor
 * @author Piotr Wlodarczyk
 *
 */
public class DflMultiPageEditor extends MultiPageEditorPart implements IResourceChangeListener {
	private DflEditor diagramEditor;
	private int editorIndex;
	private int descriptionIndex;
	private Text descriptionField;
	
	 /** the selection listener */
    private ISelectionListener selectionListener = new ISelectionListener(){
        public void selectionChanged(IWorkbenchPart part, ISelection selection){
            if(diagramEditor!=null) diagramEditor.updateActions();
        }
    };
    
	public DflMultiPageEditor() {
		super();
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
	}
	
	@Override
	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		super.init(site, input);
		// add selection change listener
        getSite()
            .getWorkbenchWindow()
            .getSelectionService()
            .addSelectionListener(
            selectionListener);
	}
	
	protected boolean dirty = false;
	public boolean isDirty() {
       return (dirty || diagramEditor.isDirty());
    }
    protected void setDirty(boolean value) {
       dirty = value;
       firePropertyChange(PROP_DIRTY);
    }
    
	@Override
	public void dispose() {
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
		if(diagramEditor!=null) diagramEditor.dispose();

        // remove selection listener
        getSite()
            .getWorkbenchWindow()
            .getSelectionService()
            .removeSelectionListener(
            selectionListener);
        
		super.dispose();
	}
	
	@SuppressWarnings("deprecation") //$NON-NLS-1$
	@Override
	public String getTitle() {
		if(getEditorInput()!=null){
			setTitle(getEditorInput().getName());
			return getEditorInput().getName();
		}
		return super.getTitle();
	}
	
	@Override
	protected void createPages() {
		createPage0();
		createPage1();
		setActiveEditor(diagramEditor);
		
		getSite().getWorkbenchWindow().addPageListener(new IPageListener(){
			public void pageActivated(IWorkbenchPage page) {
				page.addPartListener(new IPartListener(){
					public void partActivated(IWorkbenchPart part) {
						if( part instanceof DflMultiPageEditor){
							DflMultiPageEditor editor = (DflMultiPageEditor) part;
							if(editor.getDiagramEditor()!=null){
								String perspectiveID = "org.dfl.plugin.perspectives.dflperspective"; 
								if(editor.getDiagramEditor().getModel().isRunnning()){
									perspectiveID = "org.dfl.plugin.perspectives.debugperspective";
								}
								try {
									WorkbenchUtil.getActiveWindow().getWorkbench().showPerspective(perspectiveID,
											WorkbenchUtil.getActiveWindow());
								} catch (WorkbenchException e) {
								}
							}
						}
					}
					public void partBroughtToTop(IWorkbenchPart part) {	}
					public void partClosed(IWorkbenchPart part) {}
					public void partDeactivated(IWorkbenchPart part) {}
					public void partOpened(IWorkbenchPart part) {}});
			}

			public void pageClosed(IWorkbenchPage page) {}
			public void pageOpened(IWorkbenchPage page) {}});
	}

	private void createPage0() {
		try {
			diagramEditor = new DflEditor();
			editorIndex = addPage(diagramEditor, getEditorInput());
			setPageText(editorIndex, Messages.DflMultiPageEditor_1);
		} catch (PartInitException e) {
			ErrorDialog.openError(
				getSite().getShell(),
				Messages.DflMultiPageEditor_2,
				null,
				e.getStatus());
		}
	}
	

	private void createPage1() {
		Composite composite = new Composite(getContainer(), SWT.NONE);
		FillLayout layout = new FillLayout();
		composite.setLayout(layout);

		descriptionField = new Text(composite,SWT.MULTI | SWT.WRAP);
		if(diagramEditor!=null && diagramEditor.getModel()!=null){
			descriptionField.setText(diagramEditor.getModel().getDesctiption());
		}
		
		descriptionField.addModifyListener(new ModifyListener(){
			public void modifyText(ModifyEvent e) {
				if(diagramEditor!=null && diagramEditor.getModel()!=null){
					String oldDesc = diagramEditor.getModel().getDesctiption();
					String newDesc = descriptionField.getText();
					if(!oldDesc.equals(newDesc)){
						diagramEditor.getModel().setDesctiption(newDesc);
						setDirty(true);
					}
				}
			}});
		
		descriptionIndex = addPage(composite);
		setPageText(descriptionIndex, Messages.DflMultiPageEditor_3);
	}

	@Override
	public void doSave(IProgressMonitor monitor) {
		getEditor(0).doSave(monitor);
		setDirty(false);
	}

	@Override
	public void doSaveAs() {
		// nothing - not allowed in isSaveAsAllowed
		IEditorPart editor = getEditor(0);
		editor.doSaveAs();
		setPageText(0, editor.getTitle());
		setInput(editor.getEditorInput());
		setDirty(false);
	}
	
	@Override
	public boolean isSaveAsAllowed() {
		return false;
	}

	/**
	 * Closes all project files on project close.
	 */
	public void resourceChanged(final IResourceChangeEvent event){
		if(event.getType() == IResourceChangeEvent.PRE_CLOSE || event.getType() == IResourceChangeEvent.PRE_DELETE){
			Display.getDefault().asyncExec(new Runnable(){
				public void run(){
					IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
					for (int i = 0; i<pages.length; i++){
						if(((FileEditorInput)diagramEditor.getEditorInput()).getFile().getProject().equals(event.getResource())){
							IEditorPart editorPart = pages[i].findEditor(diagramEditor.getEditorInput());
							pages[i].closeEditor(editorPart,true);
						}
					}
				}            
			});
		}
	}

	/* (non-Javadoc)
	 * Method declared on IEditorPart
	 */
	public void gotoMarker(IMarker marker) {
		setActivePage(0);
		IDE.gotoMarker(getEditor(0), marker);
	}
	
	@Override
	protected void pageChange(int newPageIndex) {
		if(newPageIndex == descriptionIndex && diagramEditor!=null && diagramEditor.getModel()!=null){
			descriptionField.setText(diagramEditor.getModel().getDesctiption());
		}
		super.pageChange(newPageIndex);
	}
	public DflEditor getDiagramEditor() {
		return diagramEditor;
	}
}
